객체 설계 할 때 데이터 중심이 아닌 책임 중심으로 해야 하는 이유

추상화, 결합도, 응집도를 잘 활용해야 변경에 유연해 진다.

Posted by Yungwang Ryu on 2019-07-29

왜 OOP를 할 때 데이터 중심으로 하면 안될까??

데이터는 구현이다. 여기서 말하는 구현은 객체의 상태값이 될수도 있고 객체가 수행하는 로직이 될 수 도 있다. 즉, 객체 내부에서만 접근 가능한 것들이다.
구현은 얼마든지 변경이 생길수 있기 때문에 데이터 중심으로 객체간 협력을 하게 되면 변경에 취약하게 된다.

책임은 인터페이스다. 책임 중심으로 이 객체는 어떤 책임을 가져야하는가? 라는 물음으로 객체를 설계하면 객체의 내부 구현은 캡슐화 화면서 설계 할 수 있기 때문에
코드 응집도 높고 변경에 유연한 설계를 얻을 수 있게 된다.

데이터 중심 객체 설게 문제점 1 - 캡슐화 위반

객체가 어떤 책임을 가져야 하는지 알 수 있을려면 이 객체가 다른 객체와 어떤 협력을 해야햐는지 파악되야 어떤 책임을 가져야 하는지 알게 되는 것이다.
즉 협력이 있어야 책임도 있는 것이다. 그러한 반면에 데이터 중심 객체 설계는 이 객체가 어떤 협력과 책임은 고려하지 않고 오직 어떠한 데이터가 필요한지에만 관심이 있다.
이렇게 되면 개발자는 앞으로 어떤 데이터로 협력 될지 모르리 때문에 과도하게 접근자, 수정자를 추가하게 된다. 즉 캡슐화를 위반하기 쉽게 되는 상황을 만든다는 것이다.

추측에 의한 설계가 아닌 객체가 어떤 협력을 하는지 명확히 인지한 상태에서 어떠한 책임을 가져야하는지 알고 객체를 설계 해야 하는 것이다.

데이터 중심 설계 객체 예제

1
2
3
4
5
6
7
8
9
10
11
12
public class Movie {
private String title;
private Duration runningTime;
private Money fee;
private List<DiscountCondition> discountConditions;

private MovieType movieType;
private Money discountAmount;
private double discountPercent;

// getter, setter..
}

과도하게 많은 데이터를 포함하게 되고 접근자, 수정자를 만들어 객체 캡슐화를 위반하게 만든다.

책임 중심 설계 객체 예제

1
2
3
4
5
6
7
8
public class Movie {
private String title;
private Duration runningTime;
private Money fee;
private DiscountPolicy discountPolicy;

// getter, setter..
}

Movie 객체에 역활은 영화에 대한 정보를 가지고 있어야 하고 그 정보를 다른 객체 (예약, 상영)에서 활용하게 된다.
하지만 Movice 책임 영화에 대한 정보만 있으면 돤다. 영화 할인 정책에 관한 처리는 따른 객체 DiscountPolicy 에게 위임 또는 협력하여 정보를 가져오면 되는 것이다.

데이터 중심 객체 설게 문제점 2 - 높은 결합도

객체에 과도하게 많은 접근자와 수정자가 생격 다른 객체에서 접근하여 사용 할 확률이 높다. 그렇게 되면 수정사항이 발생하면 사용한 객체들에게 모두 영향을 미치게 된다.

1
2
3
4
5
6
public class ReservationAgency {
public Reservation reserve(Screening screening, Customer customer, int audienceCount) {
// ...
fee = movie.getFee().minus(discountAmount).times(audienceCount);
}
}

movie.getFee() 리턴 타입이 변경되면 어떻게 될까?? .getFee()를 하는 모든 객체 타입을 변경해줘야한다.

데이터 중심 객체 설게 문제점 3 - 낮은 응집도

서로 다른 이유로 변경되는 코드가 하나의 모듈 안에 공존할 때 모듈의 응집도가 낮다고 말한다.

이것또한 과도한 접근을 허용하게 되어 여러 객체에서 접근하여 로직을 작성하다 보니 하나에 객체에 많은 접근자가 있을 것이고 어떠한 이유로 수정하려 하는데
다른 객체에 영향을 미치게 한다는 것이다. 다 캡슐화를 위반하게 만들어서 발생하는 이유이다.

정리

이 모든 문제는 데이터 중심으로 객체를 설계하다 보니 숨겨야 할 상태들을 숨기지 않고 인터페이스로 노출시켜 여러 객체들에 의존성이 강하게 결합되어 변경에 취약하게 된 것이다.
즉, 캡슐화가 깨져서 그런 것이다. 따라서 객체간에 어떠한 협력을 하는지 생각하고 책임중심으로 설계해야 캡슐화에 이점을 가지고 변경에 유연한 설계를 가질수 있게 된다.

앞으로 실무에서 보게 되는 클래스로 보지 말고 이 객체가 어떻게 협력하고 있는지를 그 문맥을 기반으로 캡슐화가 잘 되어 있는지 생각하면서 수정, 개발을 해야겠다.
그래야 진정으로 책임 중심 객체 설계를 해야 하는 이유를 머릿속에 각인이 될 것이기 때문이다.